/*
 * DocumentSource.java
 *
 * Created on July 17, 2003, 10:10 PM
 */

package org.infoset.xml.util;

import java.util.*;
import org.infoset.xml.*;

/**
 *
 * @author  alex
 */
public class DocumentSource extends EmptySource {
   
   Stack context;
   boolean started;
   boolean makeDocument;
   boolean docMade;
   Parent currentParent;
   Iterator<Child> currentChildren;
   ItemConstructor constructor;
   /** Creates a new instance of DocumentSource */
   public DocumentSource(Parent top,boolean makeDocument) {
      context = new Stack();
      started = false;
      currentParent = top;
      docMade = false;
      currentChildren = top.iterator();
      constructor = top.getInfoset().createItemConstructor();
      this.makeDocument = makeDocument || top.getType()==Item.ItemType.DocumentItem;
   }
   
   public Item receive() 
      throws XMLException
   {
      if (started) {
         // We're done if this is null
         if (currentParent==null) {
            return null;
         }
         
         // If we have children, we're still working
         if (currentChildren==null) {
            if (makeDocument && docMade) {
               Item toReturn = constructor.createDocumentEnd();
               currentParent = null;
               return toReturn;
            } else {
               currentParent = null;
               return null;
            }
         } else if (currentChildren.hasNext()) {
            Child c = (Child)currentChildren.next();
            if (c.getType()==Item.ItemType.ElementItem) {
               context.push(currentParent);
               context.push(currentChildren);
               currentParent = (Parent)c;
               currentChildren = currentParent.iterator();
            }
            return ItemProperties.copyOf(constructor,(Item)c);
         } else if (currentParent.getType()==Item.ItemType.ElementItem) {
            Element e = (Element)currentParent;
            if (context.empty()) {
               currentChildren = null;
            } else {
               currentChildren = (Iterator)context.pop();
               currentParent = (Parent)context.pop();
            }
            return constructor.createElementEnd(e);
         } else {
            currentChildren = null;
            currentParent = null;
            return constructor.createDocumentEnd();
         }
      } else {
         if (makeDocument && !docMade && currentParent.getType()!=Item.ItemType.DocumentItem) {
            docMade = true;
            return constructor.createDocument(currentParent.getBaseURI());
         } else if (makeDocument) {
            started = true;
            return ItemProperties.copyOf(constructor,(Item)currentParent);
         } else {
            started = true;
            return ItemProperties.copyOf(constructor,(Item)currentParent);
         }         
      }
   }
   
   public static void generate(Parent item,boolean makeDocument,ItemDestination dest) 
      throws XMLException
   {
      DocumentSource source = new DocumentSource(item,makeDocument);
      Item i;
      while ((i=source.receive())!=null) {
         dest.send(i);
      }
   }
   
}
